package cn.com.surker.production.controller;

import cn.com.surker.base.BaseEntity;
import cn.com.surker.common.Code;
import cn.com.surker.enums.ICodeDescEnum;
import cn.com.surker.enums.StateEnum;
import cn.com.surker.enums.production.invoice.BackTypeEnum;
import cn.com.surker.enums.production.invoice.ShipTypeEnum;
import cn.com.surker.enums.production.invoice.TranTypeEnum;
import cn.com.surker.enums.system.IsAutoEnum;
import cn.com.surker.handler.DisCoordinator;
import cn.com.surker.production.entity.InvoiceHandle;
import cn.com.surker.production.entity.ProductionInvoice;
import cn.com.surker.production.entity.TranCar;
import cn.com.surker.production.entity.vo.InvoiceHandleDetail;
import cn.com.surker.production.entity.vo.ProductionInvoiceVo;
import cn.com.surker.spring.RestResultDto;
import cn.com.surker.system.model.CacheUser;
import cn.com.surker.util.DateUtil;
import cn.com.surker.util.MathUtils;
import cn.com.surker.util.StringUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.transaction.RollbackException;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 发货单退料处理记录
 * </p>
 *
 * @author admin
 * @since 2024-09-26
 */
@RestController
@RequestMapping("/pro/invoice/back")
public class InvoiceBackController extends ProBaseController {

	@Autowired
	private DisCoordinator disCoordinator;

	/**
	 * 退料列表
	 * @param startDate
	 * @param endDate
	 * @param conName
	 * @param site
	 * @param isAuto        是否自动生成,0自动,1手动
	 * @param handle        是否有处理记录:0没有处理记录,1有处理记录
	 * @param pageIndex
	 * @param limit
	 * @return
	 */
	@RequestMapping(value = "/page", method = RequestMethod.POST)
	@ResponseBody
	public RestResultDto backPage(String startDate, String endDate, String conName, String site, Integer isAuto, Integer handle, Integer pageIndex, Integer limit) {
		if (pageIndex == null) {
			pageIndex = 1;
		}
		if (limit == null) {
			limit = 50;
		}
		IPage<InvoiceHandleDetail> backPage = invoiceHandleService.findInvBackPage(erpDb, startDate, endDate, conName, site, null, null, isAuto, handle, pageIndex, limit);
		return RestResultDto.success(backPage);
	}

	@RequestMapping(value = "/nearly", method = RequestMethod.POST)
	@ResponseBody
	public RestResultDto nearlyBackList() {
		Object o = null;
		try {
			o = memoryCache.get(DisCoordinator.backInvKey);
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (o == null) {
			//	没有查询出信息,直接从数据库查询
			o = disCoordinator.nearlyBackList();
		}
		return RestResultDto.success(o);
	}

	/**
	 * 新增退料记录
	 *
	 * @param invoiceId        发货单
	 * @param reType            退料类型
	 * @param weightStere        过磅重量
	 * @param weightTime        退回时间
	 * @return
	 */
	@RequestMapping(value = "/add", method = RequestMethod.PUT)
	@ResponseBody
	@Transactional(rollbackFor = RollbackException.class, propagation = Propagation.REQUIRED)
	public RestResultDto add(Long invoiceId, Integer reType, Double weightStere, @DateTimeFormat(pattern = DateUtil.DATE_DETAIL_FORMATTER) Date weightTime, String remark) {

		if (invoiceId == null) {
			return RestResultDto.fail("请选择发货单");
		}
		if (weightStere == null || weightStere <= 0) {
			return RestResultDto.fail("请输入过磅余量");
		}
		BackTypeEnum backTypeEnum = ICodeDescEnum.getEnum(BackTypeEnum.class, reType);
		if (backTypeEnum == null) {
			return RestResultDto.fail("请选择退回类型");
		}
		if (weightTime == null) {
			return RestResultDto.fail("请选择退回时间");
		}
		//	查询发货单
		ProductionInvoiceVo invoice = invoiceService.queryOverview(erpDb, orgId, invoiceId);
		if (!BaseEntity.validateExist(invoice)) {
			return RestResultDto.fail("发货单不存在或已经被删除");
		}
		//	发货方量
		Double sendStere = invoice.getSendStere();
		if (sendStere == null) {
			return RestResultDto.fail("该发货单发货方量为空,请检查发货单数据");
		}
		//	生产方量
		Double proStere = invoice.getProStere();
		Long erpId = invoice.getErpId();
		if (erpId != null && erpId > 0) {
			//	暂时改为发货方量
			proStere = invoice.getSendStere();
		}
		if (proStere == null) {
			return RestResultDto.fail("该发货单生产方量为空,请检查发货单数据");
		}
		if (weightStere > proStere) {
			return RestResultDto.fail("过磅退回方量不能大于生产方量");
		}
		//	查询该发货单是否存在过退砼
		InvoiceHandle oldHandle = invoiceHandleService.queryBackByInvId(orgId, invoiceId);
		if (oldHandle != null) {
			return RestResultDto.fail("该发货单下已存在退砼记录,不允许新增,如有更改,请修改数据");
		}
		//	验证完毕,更改发货单数据
		//invoice.setSignStere(signStere);
		invoiceService.updateById(invoice);
		CacheUser user = getUser();
		//	创建数据
		InvoiceHandle backOperate = new InvoiceHandle();
		backOperate.setSourceOrgId(orgId);
		backOperate.setSourceInvoiceId(invoiceId);
		backOperate.setOperateType(ShipTypeEnum.BACK_SCRAP_WEIGHT.getCode());
		backOperate.setReType(reType);
		backOperate.setOperateStere(weightStere);
		//	过磅方量
		backOperate.setWeightStere(weightStere);
		backOperate.setWeightTime(weightTime);
		backOperate.setCreator(user.getName());
		backOperate.setCreateTime(new Date());
		backOperate.setRemark(remark);
		backOperate.setIsAuto(IsAutoEnum.SD.getCode());
		//	保存数据
		invoiceHandleService.save(backOperate);
		/*//	设置发货单退回方量
		invoice.setReStere(weightReStere);
		// 	更新发货单信息
		invoiceService.updateById(invoice);*/
		return RestResultDto.success();
	}

	/**
	 * 更新退货单
	 *
	 * @return
	 */
	@RequestMapping(value = "/update/{id}", method = RequestMethod.PUT)
	@ResponseBody
	@Transactional(rollbackFor = RollbackException.class, propagation = Propagation.REQUIRED)
	public RestResultDto update(@PathVariable Long id, Integer reType, Double weightStere, Double expectStere, @DateTimeFormat(pattern = "YYYY-MM-DD HH:mm:ss") Date weightTime, Integer isWork, String remark) {
		if (id == null) {
			return RestResultDto.fail("请选择正确的退货单");
		}
		InvoiceHandle backOperate = invoiceHandleService.getById(id);
		if (!BaseEntity.validateExist(backOperate) || !ShipTypeEnum.BACK_SCRAP_WEIGHT.getCode().equals(backOperate.getOperateType())) {
			return RestResultDto.fail("退回单不存在或已经删除");
		}
		if (weightStere == null || weightStere <= 0) {
			return RestResultDto.fail("请输入过磅余量");
		}
		/*if (expectStere == null || expectStere <= 0) {
			return RestResultDto.fail("请输入客户退回方量");
		}*/
		BackTypeEnum backTypeEnum = ICodeDescEnum.getEnum(BackTypeEnum.class, reType);
		if (backTypeEnum == null) {
			return RestResultDto.fail("请选择退回类型");
		}
		if (weightTime == null) {
			return RestResultDto.fail("请选择退回时间");
		}
		//	验证过磅余量是否充足
		Double oldWeightStere = backOperate.getWeightStere();
		if (weightStere < oldWeightStere) {
			//	新的余料小于旧的,判断该退货单中处理的发货单
			List<InvoiceHandleDetail> operateList = invoiceHandleService.findByPId(id);
			if (operateList != null && operateList.size() > 0) {
				//	存在操作记录,验证操作方量
				Double handleStere = 0d;
				for (int i = 0, s = operateList.size(); i < s; i++) {
					//	转出的方量
					InvoiceHandle item = operateList.get(i);
					Double stere = item.getOperateStere();
					handleStere = MathUtils.add(handleStere, stere);
				}
				// 判断操作过的方量是否大于新设定的数据
				if (handleStere > weightStere) {
					return RestResultDto.fail("该退货单已经有过转料/作废操作记录,累计操作方量为:" + handleStere + "方,变更余料不能小于该数值");
				}
			}
		}
		CacheUser user = getUser();
		String userName = user.getName();
		backOperate.setWeightStere(weightStere);
		backOperate.setWeightTime(weightTime);
		backOperate.setOperateStere(weightStere);
		backOperate.setExpectStere(expectStere);
		backOperate.setReType(reType);
		backOperate.setRemark(remark);
		backOperate.setIsWork(isWork);
		backOperate.setUpdator(userName);
		invoiceHandleService.updateById(backOperate);
		/*//	更新发货单数据
		ProductionInvoice invoice = invoiceService.getById(backOperate.getSourceInvoiceId());
		//	设置发货单退回方量
		invoice.setReStere(weightReStere);
		// 	更新发货单信息
		invoiceService.updateById(invoice);*/
		return RestResultDto.success();
	}

	/**
	 * 删除退货单
	 *
	 * @return
	 */
	@RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
	@ResponseBody
	@Transactional(rollbackFor = RollbackException.class, propagation = Propagation.REQUIRED)
	public RestResultDto delete(@PathVariable Long id) {
		if (id == null) {
			return RestResultDto.fail(Code.PARAM_EMPTY);
		}
		InvoiceHandle backOperate = invoiceHandleService.getById(id);
		if (!BaseEntity.validateExist(backOperate)) {
			return RestResultDto.fail("该退货单不存在或已经被删除");
		}
		//	查询是否存在转料/作废操作
		List<InvoiceHandleDetail> operateList = invoiceHandleService.findByPId(id);
		if (operateList != null && operateList.size() > 0) {
			return RestResultDto.fail("该退货单存在转料/作废操作,记录,请先清除相关操作记录");
		}
		backOperate.setStatus(StateEnum.DISABLED.getCode());
		invoiceHandleService.updateById(backOperate);
		return RestResultDto.success();
	}

	/**
	 * 处理退回
	 *
	 * @param id        退砼单id
	 * @param type      处理类型
	 * @param stere     操作方量
	 * @param invoiceId 如果是转出,则需要关联发货单
	 * @param isAdd        源发货单是否累计
	 * @return
	 */
	@RequestMapping(value = "/handle/{id}", method = RequestMethod.PUT)
	@ResponseBody
	@Transactional(rollbackFor = RollbackException.class, propagation = Propagation.REQUIRED)
	public RestResultDto handle(@PathVariable Long id, Integer type, Double stere, Long invoiceId, Integer isAdd, Double sendStere, String remark) {
		if (id == null) {
			return RestResultDto.fail("请选择正确的退砼单");
		}

		if (stere == null || stere <= 0) {
			return RestResultDto.fail("请输入正确的处理方量");
		}
		//	查询退砼单是否存在
		InvoiceHandle backRecord = invoiceHandleService.getById(id);
		if (!BaseEntity.validateExist(backRecord)) {
			return RestResultDto.fail("该退砼单不存在或者已经被删除");
		}
		//	验证退砼方量和操作方量
		Double weightReStere = backRecord.getWeightStere();
		//	查询剩余方量
		if (weightReStere < stere) {
			//	退砼总方量小于待处理方量
			return RestResultDto.fail("该退砼单总方量为:" + weightReStere + "方,小于待操作方量:" + stere + "方");
		}
		//	查询已经处理了的砼方量
		List<InvoiceHandleDetail> backOperateList = invoiceHandleService.findByPId(id);
		Double operateStere = 0d;
		if (backOperateList != null && backOperateList.size() > 0) {
			for (InvoiceHandle item : backOperateList) {
				Double oStereItem = item.getOperateStere();
				operateStere = MathUtils.add(oStereItem, operateStere);
			}
		}
		//	计算剩余量
		Double surStere = MathUtils.subtract(weightReStere, operateStere);
		if (surStere < stere) {
			return RestResultDto.fail("该退砼单总方量为:" + weightReStere + "方,已处理方量为:" + operateStere + "方,剩余" + surStere + "方,小于待操作方量:" + stere + "方");
		}
		//	退砼单关联的发货单
		Long backInvoiceId = backRecord.getSourceInvoiceId();
		CacheUser user = getUser();
		String userName = user.getName();
		Date date = new Date();
		if (ShipTypeEnum.INVOICE_SCRAP.getCode().equals(type)) {
			if (StringUtils.isBlank(remark)) {
				return RestResultDto.fail("请输入作废原因");
			}
			//	作废操作,直接操作,创建操作记录
			InvoiceHandle scrap = new InvoiceHandle();
			scrap.setSourceOrgId(orgId);
			scrap.setSourceInvoiceId(backInvoiceId);
			scrap.setOperateType(ShipTypeEnum.INVOICE_SCRAP.getCode());
			scrap.setOperateStere(stere);
			//	设置父级id
			scrap.setPid(backRecord.getId());
			scrap.setCreator(userName);
			scrap.setCreateTime(date);
			scrap.setStatus(StateEnum.ENABLED.getCode());
			scrap.setRemark(remark);
			//	保存作废记录
			invoiceHandleService.save(scrap);
		} else if (ShipTypeEnum.INVOICE_TRAN_TO_OWN.getCode().equals(type)) {
			//	转到本站操作
			/*TranTypeEnum tranTypeEnum = ICodeDescEnum.getEnum(TranTypeEnum.class, tranType);
			if (tranTypeEnum == null) {
				return RestResultDto.fail("请选择正确的转料类型");
			}*/
			//	验证发货单信息
			if (invoiceId == null) {
				return RestResultDto.fail("请选择待转入的发货单");
			}
			if (invoiceId.equals(backInvoiceId)) {
				return RestResultDto.fail("退砼单的发货单和转入发货单不能为同一个");
			}
			//	验证发货单
			ProductionInvoiceVo invoiceVo = invoiceService.queryDetail(erpDb, orgId, invoiceId);
			if (!BaseEntity.validateExist(invoiceVo)) {
				return RestResultDto.fail("目标发货单不存在或已经被删除");
			}
			//	查询车辆的载重量
			@NotNull(message = "请选择运输车辆") Long carId = invoiceVo.getCarId();
			TranCar tranCar = tranCarService.getById(carId);
			//	最大方量
			Double maxStere = tranCar.getMaxStere();
			//	验证方量,退砼方量加目标发货单方量不能大于车辆最大载重量
			Double carLoadStere = invoiceVo.getCarLoadStere();
			Double tStere = MathUtils.add(carLoadStere, stere);
			if (tStere > maxStere) {
				return RestResultDto.fail("待转入发货单的运输方量(" + carLoadStere + ")方加上本此转入方量(" + stere + ")方超过了待转入发货单运输车辆的最大运输方量(" + maxStere + ")方");
			}
			//	更新发货单数据
			// invoiceService.updateById(invoice);
			//	新增转入记录
			Integer tranType = TranTypeEnum.BATCH_TRAN.getCode();
			InvoiceHandle tranRecord = new InvoiceHandle();
			tranRecord.setSourceOrgId(orgId);
			tranRecord.setSourceInvoiceId(backInvoiceId);
			tranRecord.setTargetOrgId(orgId);
			tranRecord.setTargetInvoiceId(invoiceId);
			tranRecord.setTranType(tranType);
			tranRecord.setOperateType(ShipTypeEnum.INVOICE_TRAN_TO_OWN.getCode());
			tranRecord.setOperateStere(stere);
			tranRecord.setPid(id);
			tranRecord.setCreator(userName);
			tranRecord.setCreateTime(date);
			tranRecord.setStatus(StateEnum.ENABLED.getCode());
			tranRecord.setRemark(remark);
			//	保存转料记录
			invoiceHandleService.save(tranRecord);
			//	更新发货方量
			ProductionInvoice invoice = invoiceService.getById(invoiceId);
			if (invoice != null) {
				@NotNull(message = "请输入发货方量") Double oldSendStere = invoice.getSendStere();
				if (oldSendStere == null || !(oldSendStere.equals(sendStere))) {
					//	不一样
					invoice.setSendStere(sendStere);
					invoiceService.updateById(invoice);
				}
			}
		} else if (ShipTypeEnum.INVOICE_TRAN_TO_OTHER.getCode().equals(type)) {
			//	转移到其他站
		}
		//	更新原发货单
		if (isAdd != null) {
			ProductionInvoice invoice = invoiceService.getById(backInvoiceId);
			//	判定状态是否一致
			Integer oldAdd = invoice.getIsAdd();
			if (!isAdd.equals(oldAdd)) {
				//	不一致,需要更新
				invoice.setIsAdd(isAdd);
				invoiceService.updateById(invoice);
			}
		}
		return RestResultDto.success();
	}

	/**
	 * 查询退砼单的处理记录
	 *
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "/record/{id}", method = RequestMethod.POST)
	@ResponseBody
	public RestResultDto record(@PathVariable Long id) {
		if (id == null) {
			return RestResultDto.fail(Code.PARAM_EMPTY);
		}
		List<InvoiceHandleDetail> backOperateList = invoiceHandleService.findByPId(id);
		return RestResultDto.success(backOperateList);
	}

	/**
	 * 删除操作记录
	 *
	 * @param handleId
	 * @return
	 */
	@RequestMapping(value = "/del/record/{handleId}", method = RequestMethod.DELETE)
	@ResponseBody
	@Transactional(rollbackFor = RollbackException.class, propagation = Propagation.REQUIRED)
	public RestResultDto delRecord(@PathVariable Long handleId) {
		if (handleId == null) {
			return RestResultDto.fail(Code.PARAM_EMPTY);
		}
		//	查询操作记录
		InvoiceHandle invoiceHandle = invoiceHandleService.getById(handleId);
		if (invoiceHandle == null) {
			return RestResultDto.fail(Code.NO_DATA);
		}
		CacheUser user = getUser();
		invoiceHandle.setStatus(StateEnum.DISABLED.getCode());
		invoiceHandle.setUpdator(user.getName());
		invoiceHandleService.updateById(invoiceHandle);
		//	List<InvoiceHandle> backOperateList = invoiceHandleService.findByPId(id);
		return RestResultDto.success();
	}
}